package uk.co.accolade.clash.app.intellij;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import uk.co.accolade.clash.app.intellij.toolwindow.ClashToolWindow;
import uk.co.accolade.clash.app.intellij.vcs.ChangesListener;
import uk.co.accolade.clash.core.ChangesRegistry;
import uk.co.accolade.clash.core.Username;
import uk.co.accolade.clash.core.ChangeHandlerFactory;
import uk.co.accolade.clash.multicast.ClashMulticastComponent;
import uk.co.accolade.clash.multicast.MulticastCommunicator;

public class ClashComponent implements ProjectComponent {

    private Project project;
    private MulticastCommunicator applicationCommunicator;
    private ChangesRegistry changesRegistry;
    private ChangeHandlerFactory changeHandlerFactory;
    private IntelliJFileFacade intelliJFileFacade;
    private ClashToolWindow toolWindow;

    public ClashComponent( Project project ) {
        this.project = project;
    }

    @NonNls
    @NotNull
    public String getComponentName() {
        return "ClashComponent";
    }

    public void initComponent() {
    }

    public void disposeComponent() {
    }

    public void projectOpened() {
        init();
    }

    public void projectClosed() {
        applicationCommunicator.removeChangeHandlerFactory( changeHandlerFactory );
        toolWindow.deregister(); 
    }

    private void init() {
        loadComms();
        loadIntelliJFacade();
        loadChangesRegistry();
        registerChangeListener();
        registerUi();
    }

    private void loadComms() {
        Application application = ApplicationManager.getApplication();
        ClashMulticastComponent multicastComponent = application.getComponent( ClashMulticastComponent.class );
        applicationCommunicator = multicastComponent.getCommunicator();
    }

    private void loadIntelliJFacade() {
        intelliJFileFacade = IntelliJFileFacade.getInstance( project );
    }

    private void loadChangesRegistry() {
        changesRegistry = new ChangesRegistry(Username.systemUsername());
        changeHandlerFactory = new ChangeHandlerFactory(changesRegistry, applicationCommunicator);
        applicationCommunicator.addChangeHandlerFactory( changeHandlerFactory );
    }

    private void registerChangeListener() {
        ChangeListManager changeListManager = ChangeListManager.getInstance( project );
        ChangesListener changesListener = new ChangesListener(changeListManager, intelliJFileFacade, changeHandlerFactory);
        changeListManager.addChangeListListener( changesListener );
    }

    private void registerUi() {
        toolWindow = new ClashToolWindow( project );
        toolWindow.init();
        changesRegistry.registerClashHandler( toolWindow.getClashTree() );
    }
}